home *** CD-ROM | disk | FTP | other *** search
- include 'ioequ.inc'
-
- hamtab equ $200 ; Tabelle der Hamming-Fensterfunktion
- twiddel equ $300 ; Tabelle der complexen Drehfaktoren
- arbber equ $400 ; Arbeitsbereich
- zeitfkt equ $800 ; Eingangszeitfunktion
- size equ 512 ; Groesse des Zeitfunktionsbuffers (2*nnn)
- nnn equ 256 ; nnn-Punkte FFT
- bits equ 8 ; nnn=2^bits
-
- org y:0
- logkonst dc -0.8001568 ; Konstanten fuer Logarithmusberechnung
- dc 0.6042544
- dc -0.4106065
- dc 0.3010300
-
- org x:0
- hamaddr dc hamtab ; Konstanten im x-Speicher ablegen,
- twaddr dc twiddel ; damit mit kuerzeren Befehlen darauf
- arbaddr dc arbber ; zugegriffen werden kann
- zeitaddr dc zeitfkt
- zfktnnn dc zeitfkt+nnn
- sendflag dc 0
-
- org p:$0
- jmp <start
-
- org p:$0c ; ssi receive data
- jsr <ssirxd
- org p:$0e ; ssi receive data with Exception Status
- jsr <ssirxd
- org p:$10 ; ssi transmit data
- jsr <ssitxd
- org p:$12 ; ssi transmit data with Exception Status
- jsr <ssitxd
-
- org p:$40
-
- start movep #1,x:m_pbc ; Port B als Host-Interface
- movec #size,m3 ; modulo size adressierung
- move #zeitfkt,r3 ; Empfaengerzeiger
- movec #size,m7
- move #zeitfkt+2,r7 ; Sendezeiger (vorlaufend)
- movec #$ffff,m0 ; lineare Addressierung
- nop
- movec m0,m1
- movec m0,m2
- movec m0,m4
- movec m0,m5
- movec m0,m6
- movec #0,sp ; Stackpointer initialisieren
- movec #$0300,sr ; niedrige interrupts aus
- movep #0,x:m_bcr ; keine Waits fuer externen Speicherzugriff
- movec #0,sp ; Stackpointer initialisieren
- movep #$4700,x:m_cra ; ssi Kontrollregister A
- movep #$0800,x:m_crb ; ssi Kontrollregister B
- movep #0,x:m_pcddr ; port C ist ssi
- movep #$01f8,x:m_pcc ; ssi einschalten
- movep #$2000,x:m_ipr ; ssi interrupt auf level 1
- movec #0,sr ; interrupts aktivieren
- bset #m_srie,x:<<m_crb ; receiver interrupt einschalten
- bset #m_sre,x:<<m_crb ; receiver einschalten
- movep x:(r7),x:m_tx
- bset #m_stie,x:<<m_crb ; transmitter interrupt einschalten
- bset #m_ste,x:<<m_crb ; transmitter einschalten
-
- warte0 jclr #m_hf0,x:m_hsr,warte0 ; warte bis Host bereit
-
- ;--------------------------------------------------------------------------------------------------
-
- do_fft jclr #m_hf0,x:m_hsr,daswars ; Wenn der Host nichts mehr will
- move r3,x0 ; Teste, in welcher Haelfte gerade geschrieben wird
- move x:<zfktnnn,a ; die Mitte des Zeitbuffers
- cmp x0,a
- jpl <unten ; wenn der Zeiger in der unteren Haelfte ist
- wartunt move r3,x0 ; Zeiger ist oben, warte, bis er unten ist
- cmp x0,a
- jmi <wartunt
- move x:<zfktnnn,r5 ; Zeiger auf Zeitfunktion, obere Haelfte
- jsr <cp_x_arb ; copiere hammingbew. Zeitfkt in Arbbeitsber.
- jsr <fft ; berechne FFT
- jsr <logbetrag ; berechne den Betrag (im x-Speicher des Arbeitsbereichs)
- move x:<zfktnnn,r5 ; Zeiger auf Zeitfunktion, obere Haelfte
- jsr <cp_x_back ; zurueckkopieren
- move x:<zfktnnn,r5
- jsr <cp_y_arb ; copiere hammingbew. Zeitfkt in Arbbeitsber.
- jsr <fft ; berechne FFT
- jsr <logbetrag ; berechne den Betrag (im x-Speicher des Arbeitsbereichs)
- move x:<zfktnnn,r5 ; Zeiger auf Zeitfunktion, obere Haelfte
- jsr <cp_y_back ; zurueckkopieren
- jmp <do_fft ; weitermachen
- unten move r3,x0 ; warte, bis er oben ist
- cmp x0,a
- jpl <unten
- move x:<zeitaddr,r5 ; Zeiger auf Zeitfunktion, untere Haelfte
- jsr <cp_x_arb ; copiere hammingbew. Zeitfkt in Arbbeitsber.
- jsr <fft ; berechne FFT
- jsr <logbetrag ; berechne den Betrag (im x-Speicher des Arbeitsbereichs)
- move x:<zeitaddr,r5 ; Zeiger auf Zeitfunktion, untere Haelfte
- jsr <cp_x_back ; zurueckkopieren
- move x:<zeitaddr,r5
- jsr <cp_y_arb ; copiere hammingbew. Zeitfkt in Arbbeitsber.
- jsr <fft ; berechne FFT
- jsr <logbetrag ; berechne den Betrag (im x-Speicher des Arbeitsbereichs)
- move x:<zeitaddr,r5 ; Zeiger auf Zeitfunktion, untere Haelfte
- jsr <cp_y_back ; zurueckkopieren
- jmp <do_fft ; weitermachen
-
-
- ;--------------------------------------------------------------------------------------------------
-
- daswars bclr #m_srie,x:<<m_crb ; receiver interrupt aus
- bclr #m_stie,x:<<m_crb ; transmitter interrupt aus
- movep #0,x:m_pcc ; ssi ausschalten
- stop
-
- ;--------------------------------------------------------------------------------------------------
-
- cp_x_arb movec #0,m1 ; reverse carry Adressierung
- move x:<hamaddr,r0 ; Zeiger auf Hammingtabelle
- move #nnn/2,n1 ; fuer reverse carry im Arbeitsbereich
- move x:<arbaddr,r1 ; reverse carry Zeiger auf Arbeitsbereich
- move x:<arbaddr,r4 ; Zeiger auf Arbeitsbereich zum loeschen Imaginaerteil
- move #0,y0 ; fuer Imaginaerteil
- do #nnn,cpzhax ; so oft wie FFT gross
- move x:(r0)+,x0 ; Hammingwert holen
- move x:(r5)+,x1 ; Zeitwert holen
- mpy x0,x1,a y0,y:(r4)+ ; Zeitwert hammingbewerten, Imaginaerteil loeschen
- move a,x:(r1)+n1 ; Hammingbewerteten Zeitwert im Realteil speichern
- cpzhax
- movec #$ffff,m1
- rts
-
- ;--------------------------------------------------------------------------------------------------
-
- cp_y_arb movec #0,m1 ; reverse carry Adressierung
- move x:<hamaddr,r0 ; Zeiger auf Hammingtabelle
- move #nnn/2,n1 ; fuer reverse carry im Arbeitsbereich
- move x:<arbaddr,r1 ; reverse carry Zeiger auf Arbeitsbereich
- move x:<arbaddr,r4 ; Zeiger auf Arbeitsbereich zum loeschen Imaginaerteil
- move #0,y0 ; fuer Imaginaerteil
- do #nnn,cpzhay ; so oft wie FFT gross
- move x:(r0)+,x0 ; Hammingwert holen
- move y:(r5)+,x1 ; Zeitwert holen
- mpy x0,x1,a y0,y:(r4)+ ; Zeitwert hammingbewerten, Imaginaerteil loeschen
- move a,x:(r1)+n1 ; Hammingbewerteten Zeitwert im Realteil speichern
- cpzhay
- movec #$ffff,m1
- rts
-
- ;--------------------------------------------------------------------------------------------------
-
- cp_x_back move x:<arbaddr,r0 ; Zeiger auf Arbeitsbereich
- do #nnn,cpxloop ; nnn Werte zurueckkopieren
- move x:(r0)+,x0
- move x0,x:(r5)+
- cpxloop
- rts
- cp_y_back move x:<arbaddr,r0 ; Zeiger auf Arbeitsbereich
- do #nnn,cpyloop ; nnn Werte zurueckkopieren
- move x:(r0)+,x0
- move x0,y:(r5)+
- cpyloop
- rts
-
- ;--------------------------------------------------------------------------------------------------
-
- fft movec #$0400,sr ; scale down bit in Statusreg. setzen
- move #1,n1 ; n1=Distanz-Startwert, (Abst. zw. ob. und unt. Fluegel)
- move #nnn,n6 ; n6=twiddeloffset (Drehfaktorenabstand in Tabelle)
- do #bits,endfft ; logarithmus zur Basis 2 von N mal
- move x:<arbaddr,r0 ; r0=Zeiger auf Eingangswert Butterfly (oberen Fluegel)
- move n1,a1 ; Abstand der Fluegel berechnen (=2*Distanz)
- lsl a
- move a1,n2 ; n2=Abstand der Fluegel
- move r0,r2 ; r2=Zeiger auf ersten oberen Fluegel merken
- move n6,a1 ; Drehfaktorenabstand halbieren
- lsr a
- move a1,n6 ; merken
- do a1,nbutterfl ; Drehfakt.abst. ist auch die Anzahl der Fluegel
- move x:<twaddr,r6 ; r6=Zeiger auf Anfang Drefaktorentabelle
- move r0,r1 ; r1=Zeiger auf Eingangswert Butterfly (unterer Fluegel)
- move r0,r4 ; r4=Zeiger auf Ausgangswert Butterfly (oberer Fluegel)
- move (r1)+n1 ; Zeiger auf unteren Fluegel richten
- move r1,r5 ; r5=Zeiger auf Ausgangswert Butterfly (unterer Fluegel)
-
- ; oberer Fluegel: A=ar+jai (r0 ein, r4 aus)
- ; unterer Fluegel: B=br+jbi (r1 ein, r5 aus)
- ; Drehfaktor: C=cr+jci
-
- ; A'=A+WB=ar'+jai'=(ar+cr*br-ci*bi)+j(ai+ci*br+cr*bi)
- ; B'=A-WB=br'+jbi'=(ar-cr*br+ci*bi)+j(ai-ci*br-cr*br)=(2ar-ar')+j(2ai-ai')
-
- move x:(r1),x1 y:(r6),y0 ; Register fuer Butterfly vorbesetzen
- move y:(r0),b
- do n1,butterfl ; Butterfly fuer n1 Fluegel berechnen
- mac y0,x1,b x:(r6)+n6,x0 y:(r1)+,y1
- macr x0,y1,b y:(r0),a
- subl b,a x:(r0),b b,y:(r4)
- mac x0,x1,b x:(r0)+,a a,y:(r5)
- macr -y0,y1,b x:(r1),x1 y:(r6),y0
- subl b,a b,x:(r4)+ y:(r0),b
- move a,x:(r5)+
- butterfl
- move (r2)+n2 ; Zeiger auf naechsten Butterfly berechnen
- move r2,r0 ; und Zeiger auf oberen Fluegel darauf richten
- nbutterfl
- move n2,n1 ; Neue Distanz = alter Fluegelabstand
- endfft
- rts
-
- ;--------------------------------------------------------------------------------------------------
-
- logbetrag movec #0,sr ; Statusregister Initialisieren
- move #arbber+1,r0 ; r0=Zeiger auf Eingangswert (Tabellenanfang)
- move #arbber+nnn-1,r1 ; r1=Zeiger auf Ausgangswert (Tabellenende)
- move r0,r4 ; r4=Zeiger auf Ausgangswert (Tabellenanfang)
- move r1,r5 ; r5=zeiger auf Eingangswert (Tabellenende)
-
- ; A=ar+jai (r0 ein)
- ; B=br+jbi (r5 ein)
-
- ; B=A* (B und A sind konjugiert Komplex)
- ; lg(|A|^2)=lg(|B|^2)=lg(ar*br-ai*bi)
-
- move x:(r0),x0 y:(r5),y0
- move x:(r5)-,x1 y:(r0)+,y1
- do #nnn/2,betrloop
- mpy x0,x1,a ; quadrieren
- mpy y0,y1,b
- sub b,a
- move a,x:(r1)- ; Betragsquadrate im x-Speicher ablegen
-
- ; Berechnet log10(a) auf 2 Dezimalstellen nach dem Komma genau
- ; durch quatratisch Naeherung
- ; Eingang: a, Ausgang: b
- ; Zahlendarstellung fuer Ausgangswert:
- ; Kennzahl*65536+Mantisse
-
- clr b
- cmp a,b ; test, ob Eingangswert<=0
- move b0,r2 ; Exponenten rueckstzen
- jge <logundef ; wenn Zahl <=0, undefiniert
- move a1,x0 ; sonst oberen Teil testen
- cmp x0,b ; wenn oberer Teil!=0,
- jne <logloop ; dann normal log berechnen
- move #<24,r2 ; sonst nur a0>0, Exponenten erhoehen
- move a0,a1 ; und unteren Teil heranziehen
- move b0,a0
- asr a (r2)- ; ersten Schleifendurchlauf korrigieren
- logloop asl a (r2)+ ; Exponenten ermitteln (in r2 zaehlen)
- jec <logloop
- asr a (r2)- ; Exponent ist eins zu hoch
- move r2,x0 ; Exponenten merken
- move #logkonst,r2 ; Konstantentabelle
- move a,y0 ; Mantisse (x)
- mpy y0,y0,a ; Mantisse^2 (x^2)
- move a,x1 ; merken
- move y:(r2)+,a ; konsta0 in a_accu (y=a0)
- move y:(r2)+,y1 ; konsta1 in y1
- mpy +y0,y1,b y:(r2)+,y1 ; (a1/2*x) in b_accu, konsta2 in y1
- addl a,b x:(r5),x1 ; (y=a0+a1*x) in b_accu, x1 fuer Betragsberech. laden
- mac +x1,y1,b y:(r2)+,y1 ; (y=a0+a1*x+a2*x^2) in b_accu, y1 fuer Betrag
- asr b ; normieren (die rep-Anweisung ist hier nicht geeignet,
- asr b ; da sie von Interrupts nicht unterbrochen werden kann.)
- asr b
- asr b
- asr b
- asr b
- asr b
- mpy x0,y1,a y:(r5)-,y0 ; Kennziffer berechnen, y0 fuer Betrag
- asr a ; passend machen
- asr a
- asr a
- asr a
- asr a
- asr a
- asr a
- asr a
- move a0,y1 ; und zur Mantisse dazu
- sub y1,b x:(r0),x0 ; x0 fuer Betrag
- jmp <logend
- logundef move #$ce0000,b ; Wert fuer ungueltig (-50)
-
- logend move b,x:(r4)+ y:(r0)+,y1 ; und speichern
- betrloop
- move #$800000,x0 ; Endekennzeichen
- move x0,x:(r4)+
- rts
-
- ;--------------------------------------------------------------------------------------------------
-
- ssirxd jclr #<m_sre,x:m_crb,ssirxdy ; abwechselnd in x u. y ablegen, Flag: sre
- movep x:m_rx,x:(r3) ; 1. Wert in x-Speicher ablegen
- bclr #<m_sre,x:<<m_crb ; Flag setzen
- rti
- ssirxdy movep x:m_rx,y:(r3)+ ; 2. Wert in y-Speicher ablegen
- bset #<m_sre,x:<<m_crb ; receiver fuer naechsten Frame aktivieren
- rti
-
- ssitxd jset #<1,x:<sendflag,ssitxdx ; abwechselnd x u. y senden, Flag: sendflag
- movep y:(r7)+,x:m_tx ; 2. Wert senden
- bset #<1,x:<sendflag ; Flag setzen
- rti
- ssitxdx movep x:(r7),x:m_tx ; 1. Wert ins Senderegister
- bclr #<1,x:<sendflag ; Flag loeschen
- bclr #<m_ste,x:<<m_crb ; Senden nach Wert in Schiebereg. stoppen
- bset #<m_ste,x:<<m_crb
- rti
-
- ;--------------------------------------------------------------------------------------------------
-
- org x:hamtab
- include 'ham256.a56'
-
- org x:twiddel
- include 'tw128x.a56'
- org y:twiddel
- include 'tw128y.a56'
-
- end